<?php
/*
 * @Author: your name
 * @Date: 2020-10-14 16:47:40
 * @LastEditTime: 2020-12-30 14:44:23
 * @LastEditors: Please set LastEditors
 * @Description: 防火墙原始规则
 * @FilePath: /special/application/adminapiv3/service/module_manage/netfilter/FirewallOriginRuleService.php
 */
namespace app\adminapiv3\service\module_manage\netfilter;

use app\adminapiv3\service\BaseService;
use app\common\definition\HostDefinition;
use app\common\exception\CustomException;
use app\common\definition\netfilter\FirewallRuleDefinition;
use think\Db;
use think\Exception;

class FirewallOriginRuleService extends BaseService
{
    /**
     * @name: 原始规则列表
     * @Param: 
     * @Description: 
     * @Author: foo
     * @Date: 2019-10-31 15:42:02
     */
    public function originRuleList ($input)
    {
        $server = Db::name('HostInitialRule')->where('host_id', $input['host_id']);

        isset($input['content']) || empty($input['content']) ? : $server = $server->whereLike('content', '%' . $input['content'] . '%');

        $return = $server->paginate()->toArray();

        return $return;
    }

    /**
     * @name: 原始规则删除  (2020-11-25 暂时停用)
     * @Param: 
     * @Description: 
     * @Author: foo
     * @Date: 2019-10-31 15:42:30
     */
    public function originRuleDelete ($host_id, $rule_id_a)
    {
        $rule_a = Db::name('host_initial_rule')->field('id as rule_id, host_id, content')->where('host_id', $host_id)->whereIn('id', $rule_id_a)->where('status', FirewallRuleDefinition::RULE_ENABLE)->select();

        if (empty($rule_a))
        {
            throw new CustomException('未找到该规则', 422);
        }

        if (count(explode(',', $rule_id_a)) != count($rule_a))
        {
            throw new CustomException('参数不匹配', 422);
        }
        
        global $logArray;
        $host_name_s = $this->getHost('name', 'string');
        $rule_content = array_column($rule_a, 'content');
        $logArray = array(
            'content' => '删除原生防火墙规则',
            'old_info' => '主机:' . $host_name_s . '规则内容:' . implode(',', $rule_content)
        );

        Db::startTrans();
        try{
            
            Db::name('host_initial_rule')->whereIn('id', $rule_id_a)->where('host_id', $host_id)->delete();

            Db::name('netfilter_firewall_rule')->whereIn('rule_id', $rule_id_a)->where('host_id', $host_id)->where('source', FirewallRuleDefinition::ORIGIN_RULE_SOURCE)->delete();

            Db::commit();
        }catch (Exception $e)
        {
            Db::rollback();
            throw new CustomException($e->getMessage(), 522);
        }
        
    }

    /**
     * @name: 启用规则
     * @Param: 
     * @Description: 
     * @Author: foo
     * @Date: 2020-11-05 13:41:48
     */
    public function on ($host_id, $rule_id_a)
    {
        $rule_a = Db::name('host_initial_rule')->field('id as rule_id, host_id, content')->where('host_id', $host_id)->whereIn('id', $rule_id_a)->where('status', FirewallRuleDefinition::RULE_DISABLE)->select();

        if (empty($rule_a))
        {
            throw new CustomException('该规则不存在或已启用', 422);
        }

        if (count(explode(',', $rule_id_a)) != count($rule_a))
        {
            throw new CustomException('参数不匹配', 422);
        }
        
        global $logArray;
        $host_name_s = $this->getHost('name', 'string');
        $origin_rule_content = array_column($rule_a, 'content', 'rule_id');
        $logArray = array(
            'content' => '启用原生防火墙规则',
            'old_info' => '主机:' . $host_name_s . '规则内容:' . implode(',', $origin_rule_content)
        );
        $host_a = $this->getHost();
        $host_os = $host_a[$host_id]['os'];
        $preview_content = Db::name('netfilter_firewall_rule')->where('host_id', $host_id)->order('rank', 'ASC')->select();
        $SortRuleService = new SortRuleService();
        $preview_content = $SortRuleService->addLogRule($host_id, $preview_content);
        $preview_content = $SortRuleService->addDisguisePortRule($host_id, $host_os, $preview_content);
        if($host_os == HostDefinition::LINUX_OPERATION_SYSTEM)
        {
            $preview_content = $SortRuleService->sortRule($preview_content);
        }
        $firewall_rule_content = array_column($preview_content , 'content');
        $diff_rule_content = array_diff($origin_rule_content, $firewall_rule_content);
        if(empty($diff_rule_content))
        {
            throw new CustomException('规则已存在,无法添加该规则!!', 422);
        }
        $update_id_a = $insert_firewall_rule_a = [];
        foreach ($diff_rule_content as $rule_id => $rule_content)
        {
            $update_id_a[] = $rule_id;
            $insert_firewall_rule_a[] = [
                'source' => FirewallRuleDefinition::ORIGIN_RULE_SOURCE,
                'rank' => 0,
                'region' => FirewallRuleDefinition::UNKNOW_RULE_REGION,
                'content' => $rule_content,
                'rule_id' => $rule_id,
                'host_id' => $host_id,
            ];
        }
        
        Db::startTrans();
        try{
            Db::name('netfilter_firewall_rule')->insertAll($insert_firewall_rule_a);
            
            Db::name('host_initial_rule')->where('host_id', $host_id)->whereIn('id', $update_id_a)->update(['status' => FirewallRuleDefinition::RULE_ENABLE]);

            Db::commit();
            if($host_a[$host_id]['os'] == HostDefinition::LINUX_OPERATION_SYSTEM)
            {
                $SortRuleService = new SortRuleService();
                $SortRuleService->pushContentToFile($host_id);
            }
        } catch (Exception $e)
        {
            Db::rollback();
            throw new CustomException($e->getMessage(), 422);
        }

        $return['rule_id'] = $rule_id_a;

        return $return;
    }
    
    /**
     * @name: 禁用规则
     * @Param: 
     * @Description: 
     * @Author: foo
     * @Date: 2020-11-05 13:41:48
     */
    public function off ($host_id, $rule_id_a)
    {
        $rule_a = Db::name('host_initial_rule')->field('id as rule_id, host_id, content')->where('host_id', $host_id)->whereIn('id', $rule_id_a)->where('status', FirewallRuleDefinition::RULE_ENABLE)->select();

        if (empty($rule_a))
        {
            throw new CustomException('该规则不存在或已禁用', 422);
        }

        if (count(explode(',', $rule_id_a)) != count($rule_a))
        {
            throw new CustomException('参数不匹配', 422);
        }
        
        global $logArray;
        $host_name_s = $this->getHost('name', 'string');
        $rule_content = array_column($rule_a, 'content');
        $logArray = array(
            'content' => '禁用原生防火墙规则',
            'old_info' => '主机:' . $host_name_s . '规则内容:' . implode(',', $rule_content)
        );
        
        Db::startTrans();
        try{

            Db::name('netfilter_firewall_rule')->where('host_id', $host_id)->whereIn('rule_id', $rule_id_a)->where('source', FirewallRuleDefinition::ORIGIN_RULE_SOURCE)->delete();

            Db::name('host_initial_rule')->where('host_id', $host_id)->whereIn('id', $rule_id_a)->update(['status' => FirewallRuleDefinition::RULE_DISABLE]);
            
            Db::commit();
        } catch (Exception $e)
        {
            Db::rollback();
            throw new CustomException($e->getMessage(), 422);
        }

        $return['rule_id'] = $rule_id_a;

        return $return;
    }
}